//
//  UIControl+ButtonCon.m
//  PostDelivery
//
//  Created by wmz on 2020/7/15.
//  Copyright © 2020 wmz. All rights reserved.
//

#import "UIControl+ButtonCon.h"

@implementation UIControl (ButtonCon)
-(NSTimeInterval)timeInterval
{
  return[objc_getAssociatedObject(self,_cmd)doubleValue];
}

- (void)setTimeInterval:(NSTimeInterval)timeInterval
{
 objc_setAssociatedObject(self,@selector(timeInterval),@(timeInterval),OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

//runtime动态绑定属性

- (void)setIsIgnoreEvent:(BOOL)isIgnoreEvent{
objc_setAssociatedObject(self,@selector(isIgnoreEvent),@(isIgnoreEvent),OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (BOOL)isIgnoreEvent{
   return[objc_getAssociatedObject(self,_cmd)boolValue];
}

- (void)resetState{
  [self setIsIgnoreEvent:NO];
}

+ (void)load{

    static dispatch_once_t onceToken;

    dispatch_once(&onceToken, ^{

    SEL selA =@selector(sendAction:to:forEvent:);

    SEL selB =@selector(mySendAction:to:forEvent:);

    Method methodA =class_getInstanceMethod(self, selA);

    Method methodB =class_getInstanceMethod(self, selB);

    //将methodB的实现添加到系统方法中也就是说将methodA方法指针添加成方法methodB的返回值表示是否添加成功

    BOOL isAdd =class_addMethod(self, selA,method_getImplementation(methodB),method_getTypeEncoding(methodB));

    //添加成功了说明本类中不存在methodB所以此时必须将方法b的实现指针换成方法A的，否则b方法将没有实现。

    if(isAdd) {

    class_replaceMethod(self, selB,method_getImplementation(methodA),method_getTypeEncoding(methodA));

    }else{

    //添加失败了说明本类中有methodB的实现，此时只需要将methodA和methodB的IMP互换一下即可。

    method_exchangeImplementations(methodA, methodB);

    }

    });

}

- (void)mySendAction:(SEL)action to:(id)target forEvent:(UIEvent*)event

{
    if([self isKindOfClass:UIButton.class] && ![self isKindOfClass:NSClassFromString(@"UISwipeActionStandardButton")]) {

    self.timeInterval=self.timeInterval==0?defaultInterval:self.timeInterval;

    if(self.isIgnoreEvent){

    return;

    }else if(self.timeInterval>0){

    [self performSelector:@selector(resetState)withObject:nil afterDelay:self.timeInterval];

    }

    }

    //此处methodA和methodB方法IMP互换了，实际上执行sendAction；所以不会死循环

    self.isIgnoreEvent=YES;

    [self mySendAction:action to:target forEvent:event];
}
@end

@implementation UIButton (EnlargeEdge)

static char topNameKey;
static char leftNameKey;
static char bottomNameKey;
static char rightNameKey;

- (void)setEnlargeEdge:(CGFloat)size {
    objc_setAssociatedObject(self, &topNameKey, [NSNumber numberWithFloat:size], OBJC_ASSOCIATION_COPY_NONATOMIC);
    objc_setAssociatedObject(self, &leftNameKey, [NSNumber numberWithFloat:size], OBJC_ASSOCIATION_COPY_NONATOMIC);
    objc_setAssociatedObject(self, &bottomNameKey, [NSNumber numberWithFloat:size], OBJC_ASSOCIATION_COPY_NONATOMIC);
    objc_setAssociatedObject(self, &rightNameKey, [NSNumber numberWithFloat:size], OBJC_ASSOCIATION_COPY_NONATOMIC);
}

- (void)setEnlargeEdgeWithTop:(CGFloat)top left:(CGFloat)left bottom:(CGFloat)bottom right:(CGFloat)right {
    objc_setAssociatedObject(self, &topNameKey, [NSNumber numberWithFloat:top], OBJC_ASSOCIATION_COPY_NONATOMIC);
    objc_setAssociatedObject(self, &leftNameKey, [NSNumber numberWithFloat:left], OBJC_ASSOCIATION_COPY_NONATOMIC);
    objc_setAssociatedObject(self, &bottomNameKey, [NSNumber numberWithFloat:bottom], OBJC_ASSOCIATION_COPY_NONATOMIC);
    objc_setAssociatedObject(self, &rightNameKey, [NSNumber numberWithFloat:right], OBJC_ASSOCIATION_COPY_NONATOMIC);
}

- (CGRect)enlargedRect {
    NSNumber *topEdge = objc_getAssociatedObject(self, &topNameKey);
    NSNumber *rightEdge = objc_getAssociatedObject(self, &rightNameKey);
    NSNumber *bottomEdge = objc_getAssociatedObject(self, &bottomNameKey);
    NSNumber *leftEdge = objc_getAssociatedObject(self, &leftNameKey);

    if (topEdge && rightEdge && bottomEdge && leftEdge) {
        return CGRectMake(self.bounds.origin.x - leftEdge.floatValue,
                          self.bounds.origin.y - topEdge.floatValue,
                          self.bounds.size.width + leftEdge.floatValue + rightEdge.floatValue,
                          self.bounds.size.height + topEdge.floatValue + bottomEdge.floatValue);

    } else {
        return self.bounds;
    }
}

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
    CGRect rect = [self enlargedRect];

    if (CGRectEqualToRect(rect, self.bounds)) {
        return [super pointInside:point withEvent:event];
    }
    return CGRectContainsPoint(rect, point) ? YES : NO;
}
@end
